home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_c
/
cuj0896.zip
/
KREHBIEL.ZIP
/
PCX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-15
|
5KB
|
192 lines
Listing 4:
/*--------------------------------------------------------------
pcx.c Mode 101h PCX Viewer 1.0
----------------------------------------------------------------
Program: views VESA mode 0x101 (640x480x256) PCX files.
Usage: PCX <filename>
Build: pcx.c,vbe.c,vbe.h -> pcx.exe
Platform: IBMPC,MSDOS.
Functions:
ReadPalette Reads the palette block of a PCX file.
ReadHeader Reads the header block of a PCX file.
ReadLine Reads one scanline from a PCX file.
PcxShowFile Reads and displays a PCX file.
PcxDeinit Restores video to text mode.
main Program entry point.
Edit History:
04/12/96 C.Krehbiel. Implemented pcx.c in MSVC 1.0,
medium memory model, for MS-DOS.
--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include "vbe.h" /* vesa vbe interface */
/*--------------------------------------------------------------
Local Data
--------------------------------------------------------------*/
typedef struct /* (Abridged) header record of a PCX file */
{
char Manufacturer; /* pcx file signature: 10 */
char Version; /* pc paintbrush version */
char Encoding; /* 1: rle */
char BitsPerPixel; /* color resolution */
int Xmin,Ymin; /* image origin */
int Xmax,Ymax; /* image extent */
char NotUsed1[53]; /* not used by this program */
char Planes; /* number of color planes */
int BytesPerLine; /* (per plane) */
char NotUsed2[58]; /* not used by this program */
} pcx_t;
enum /* Error codes; also index ErrorText array below */
{
PCX_OK,PCX_EOPEN,PCX_EVIDEO,PCX_EREAD,PCX_EFORMAT
};
static const char *ErrorText[]=
{
/* PCX_OK */ "Ok",
/* PCX_EOPEN */ "File not found",
/* PCX_EVIDEO */ "Unsupported video mode",
/* PCX_EREAD */ "File read error",
/* PCX_EFORMAT */ "Invalid or unsupported format"
};
static char Line[640]; /* PCX image line buffer */
static char Palette256[768]; /* DAC palette data */
static pcx_t Header; /* PCX file header record */
/*--------------------------------------------------------------
local pcx file functions
--------------------------------------------------------------*/
static int ReadHeader(FILE *f)
/* reads the header of the open file into the global Header
structure; returns 0 on a file read error, or if the file
is not a valid pcx file, or if the pcx file does not contain
a 640x480x256-compatible image. */
{
pcx_t *h=&Header;
fread(h,sizeof(pcx_t),1,f);
return !(ferror(f) ||
h->Manufacturer!=10 || h->Encoding!=1 ||
h->Planes!=1 || h->BitsPerPixel!=8 ||
h->Ymax-h->Ymin>479 || h->Xmax-h->Xmin>639);
}
static int ReadPalette(FILE *f)
/* reads the 256-color palette of the open file into the
global buffer Palette256, and converts it to 6-bit DAC
palette register data; returns 0 on a file read error or an
invalid palette block. */
{
int i;
fseek(f,-769L,SEEK_END); /* to palette block */
if(fgetc(f)!=12) return 0; /* check signature byte */
fread(Palette256,768,1,f); /* read the 256 triplets */
if(ferror(f)) return 0;
fseek(f,128L,SEEK_SET); /* back to image data */
for(i=0;i<768;i++) Palette256[i]>>=2; /* to 6-bit rgb */
return 1;
}
static void ReadLine(FILE *f)
/* reads and decompresses the next scanline from the current
pcx file into the global Line buffer. */
{
int c,i=0;
while(i<Header.BytesPerLine)
{
c=fgetc(f);
if((c&0xc0)==0xc0) /* byte is rle block header */
{
c&=~0xc0; /* =repeat count */
memset(Line+i,fgetc(f),c); /* =pixel data */
i+=c;
}
else Line[i++]=c; /* byte is pixel data */
}
return;
}
/*--------------------------------------------------------------
general functions
--------------------------------------------------------------*/
int PcxShowFile(const char *file)
/* reads and displays a pcx file; returns 0 on success,
PCX_ error code on failure. */
{
int e=PCX_OK;
FILE *f=fopen(file,"rb");
if(!f) e=PCX_EOPEN;
else if(!ReadHeader(f)) e=PCX_EFORMAT;
else if(Header.Version==5 && !ReadPalette(f)) e=PCX_EFORMAT;
else if(!VbeSetMode(0x101)) e=PCX_EVIDEO;
else
{
int y,ymax=min(Header.Ymax,479);
int n=min(Header.Xmax,640)-Header.Xmin+1;
if(Header.Version==5) VbeSetPalette(Palette256,0,256);
for(y=Header.Ymin;y<ymax;y++)
{
ReadLine(f);
VbeWrite(Header.Xmin,y,n,Line);
}
}
if(f) fclose(f);
return e;
}
void PcxDeinit()
/* clears the image and resets the video to standard
80-column text mode */
{
VbeSetMode(3);
}
void main(int argc,char **argv)
/* displays the pcx file specified by the first argument to
the program (usage: PCX <filename>) */
{
int e=PcxShowFile(argv[1]);
if(!e)
{
getch();
PcxDeinit();
}
else puts(ErrorText[e]);
} /* main */
/*--------------------------------------------------------------------------
eof
--------------------------------------------------------------------------*/